/*
 * @Author: guangjie
 * @Github: 
 * @Date: 2019-12-11 22:46:33
 * @LastEditTime: 2021-02-25 16:08:11
 * @Description: the following code references TencentOS tiny, please keep the author information and source code according to the license.
 */

#ifndef _DOGE_LIST_H_
#define  _DOGE_LIST_H_

#define __STATIC_INLINE__ static inline

#include "stdint.h"

typedef struct d_list_node_st {
    struct d_list_node_st *next;
    struct d_list_node_st *prev;
} d_list_t;

#define DOGE_OFFSET_OF_FIELD(type, field)    \
    ((uint32_t)&(((type *)0)->field))

#define DOGE_CONTAINER_OF_FIELD(ptr, type, field)    \
    ((type *)((uint8_t *)(ptr) - DOGE_OFFSET_OF_FIELD(type, field)))

#define DOGE_LIST_NODE(node) \
    { &(node), &(node) }

#define DOGE_LIST_DEFINE(list) \
    d_list_t list = { &(list), &(list) }

#define DOGE_LIST_ENTRY(node, type, field) \
    DOGE_CONTAINER_OF_FIELD(node, type, field)

#define DOGE_LIST_FIRST_ENTRY(list, type, field) \
    DOGE_LIST_ENTRY((list)->next, type, field)

#define DOGE_LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
    (doge_list_empty(list) ? K_NULL : DOGE_LIST_FIRST_ENTRY(list, type, field))

#define DOGE_LIST_FOR_EACH(curr, list) \
    for (curr = (list)->next; curr != (list); curr = curr->next)

#define DOGE_LIST_FOR_EACH_PREV(curr, list) \
    for (curr = (list)->prev; curr != (list); curr = curr->prev)

#define DOGE_LIST_FOR_EACH_SAFE(curr, next, list) \
    for (curr = (list)->next, next = curr->next; curr != (list); \
            curr = next, next = curr->next)

#define DOGE_LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
    for (curr = (list)->prev, next = curr->prev; \
            curr != (list); \
            curr = next, next = curr->prev)

#define DOGE_LIST_FOR_EACH_ENTRY(entry, type, field, list) \
    for (entry = DOGE_LIST_ENTRY((list)->next, type, field); \
        &entry->field != (list); \
        entry = DOGE_LIST_ENTRY(entry->field.next, type, field))

#define DOGE_LIST_FOR_EACH_ENTRY_REVERSE(entry, type, field, list) \
    for (entry = DOGE_LIST_ENTRY((list)->prev, type, field); \
            &entry->field != (list); \
            entry = DOGE_LIST_ENTRY(entry->field.prev, type, field))

#define DOGE_LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, type, field, list) \
    for (entry = DOGE_LIST_ENTRY((list)->next, type, field), \
            tmp = DOGE_LIST_ENTRY(entry->field.next, type, field); \
            &entry->field != (list); \
            entry = tmp, tmp = DOGE_LIST_ENTRY(entry->field.next, type, field))

#define DOGE_LIST_FOR_EACH_ENTRY_SAFE_REVERSE(entry, tmp, type, field, list) \
    for (entry = DOGE_LIST_ENTRY((list)->prev, type, field), \
            tmp = DOGE_LIST_ENTRY(entry->field.prev, type, field); \
            &entry->field != (list); \
            entry = tmp, tmp = DOGE_LIST_ENTRY(entry->field.prev, type, field))

__STATIC_INLINE__ void _list_add(d_list_t *node, d_list_t *prev, d_list_t *next)
{
    next->prev = node;
    node->next = next;
    node->prev = prev;
    prev->next = node;
}

__STATIC_INLINE__ void _list_del(d_list_t *prev, d_list_t *next)
{
    next->prev = prev;
    prev->next = next;
}

__STATIC_INLINE__ void _list_del_node(d_list_t *node)
{
    _list_del(node->prev, node->next);
}

__STATIC_INLINE__ void doge_list_init(d_list_t *list)
{
    list->next = list;
    list->prev = list;
}

__STATIC_INLINE__ void doge_list_add(d_list_t *node, d_list_t *list)
{
    _list_add(node, list, list->next);
}

__STATIC_INLINE__ void doge_list_add_tail(d_list_t *node, d_list_t *list)
{
    _list_add(node, list->prev, list);
}

__STATIC_INLINE__ void doge_list_del(d_list_t *node)
{
    _list_del(node->prev, node->next);
}

__STATIC_INLINE__ void doge_list_del_init(d_list_t *node)
{
    _list_del_node(node);
    doge_list_init(node);
}

__STATIC_INLINE__ void doge_list_move(d_list_t *node, d_list_t *list)
{
    _list_del_node(node);
    doge_list_add(node, list);
}

__STATIC_INLINE__ void doge_list_move_tail(d_list_t *node, d_list_t *list)
{
    _list_del_node(node);
    doge_list_add_tail(node, list);
}

__STATIC_INLINE__ int doge_list_empty(const d_list_t *list)
{
    return list->next == list;
}

#endif /* _DOGE_LIST_H_ */

